#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <gmp.h>

int main(void)
{
	FILE *gauss_sequencial;
	gauss_sequencial = fopen("gauss_sequencial.txt", "w+");
	// precisao
	mpf_set_default_prec(33219281);
	
	//variaveis
	mpf_t a0; 
	mpf_t b0;
	mpf_t t0;
	mpf_t p0;
	mpf_t a1; 
	mpf_t b1;
	mpf_t t1;
	mpf_t p1;
	mpf_t PI;
	mpf_t tmp;
	int i = 0;
		
	// inicializacao
	mpf_init_set_ui(a0, 1);
	mpf_init(b0);
	mpf_init(t0);
	mpf_init_set_ui(p0, 1);
	mpf_init(a1);
	mpf_init(b1);
	mpf_init(t1);
	mpf_init(p1);
	mpf_init(PI);
	mpf_init(tmp);

	struct timeval start, end;
	int time;
	gettimeofday(&start, NULL);
	printf("Calculando pi...\n");

/* ------ VALORES INICIAIS ------ */
	
	//Raiz(2)
	mpf_sqrt_ui(tmp,2);
	// b0 = 1/raiz(2)
	mpf_ui_div(b0, 1, tmp);
	// t0 = 1/4
	mpf_div_ui(t0,a0,4);


/* ------ INICIO DO ALGORITMO ------*/
	
	for (i=0; i<25;i++) {
		
		//a1 = (a0+b0)/2
		mpf_add(a1,a0,b0);
		mpf_div_ui(a1,a1,2);
		
		//b1 = raiz(a0*b0)
		mpf_mul(b1, a0,b0);
		mpf_sqrt(b1,b1);
		
		//t1 = t0 - p0*[(a0-a1)ˆ2]
		mpf_sub(tmp,a0,a1);
		mpf_pow_ui(tmp,tmp,2);
		mpf_mul(t1, p0, tmp);
		mpf_sub(t1, t0,t1);
		
		//p1 = 2*p0
		mpf_mul_ui(p1,p0,2);
		
		// PI = (a0+b0)ˆ2 / 4*t0
		mpf_add(tmp, a0, b0);
		mpf_pow_ui(tmp, tmp, 2);
		mpf_mul_ui(PI, t0, 4);
		mpf_div(PI,tmp,PI);
		
		// imprimindo PI no arquivo
		mpf_out_str(gauss_sequencial,10,0,PI);
		
		// guardando novos valores
		mpf_set(a0, a1);
		mpf_set(b0, b1);
		mpf_set(t0, t1);
		mpf_set(p0, p1);
		
	}

	printf("Pronto.\n");

	gettimeofday(&end, NULL);
	time = end.tv_sec - start.tv_sec;

	printf("\nNumero de iteracoes: %d\nTempo para calculo: %d segundos\n", i, time);
	
	//libera memoria
	mpf_clear(a0);
	mpf_clear(a1);
	mpf_clear(b0);
	mpf_clear(b1);
	mpf_clear(t0);
	mpf_clear(t1);
	mpf_clear(p0);
	mpf_clear(p1);
	mpf_clear(PI);
	mpf_clear(tmp);
		
	return EXIT_SUCCESS;
}
